package org.wh1tew0lf.vframe.framework;

import java.util.Date;
import java.util.Map;

import org.wh1tew0lf.vframe.framework.vframeexception.VDatabaseRestrictionValueIsNullException;
import org.wh1tew0lf.vframe.framework.vframeexception.VDatabaseRestrictionValueTypeNotSupportedException;
import org.wh1tew0lf.vframe.framework.vframeexception.VDatabaseRestrictionValuesIsNullException;
import org.wh1tew0lf.vframe.framework.vframeexception.VFieldNameIsNullException;
import org.wh1tew0lf.vframe.framework.vframeexception.VFrameException;
import org.wh1tew0lf.vframe.framework.vframeexception.VLogicOperatorIsNullException;
import org.wh1tew0lf.vframe.framework.vframeexception.VOperatorIsNullException;

public final class VDatabaseRestriction implements IDatabaseRestriction {

	private VDatabaseField fieldName;
	private boolean restrictionElement;
	private VDatabaseRestrictionOperator operator;
	private VDatabaseRestrictionLogicOperator logicOperator;
	private VDatabaseValue[] values;
	private VDatabaseRestriction[] restrictions;

	public static VDatabaseRestriction newWithFieldAndValue(String fieldName,
			VDatabaseRestrictionOperator operator, VDatabaseValue... values)
			throws VFrameException {
		return new VDatabaseRestriction(VDatabaseField.field(fieldName),
				operator, values);
	}

	protected static VDatabaseRestriction newWithFieldAndValue(String fieldName,
			VDatabaseRestrictionOperator operator, Number value)
			throws VFrameException {
		return new VDatabaseRestriction(VDatabaseField.field(fieldName),
				operator, VDatabaseValue.number(value));
	}

	protected static VDatabaseRestriction newWithFieldAndValue(String fieldName,
			VDatabaseRestrictionOperator operator, String value)
			throws VFrameException {
		return new VDatabaseRestriction(VDatabaseField.field(fieldName),
				operator, VDatabaseValue.string(value));
	}

	protected static VDatabaseRestriction newWithFieldAndValue(String fieldName,
			VDatabaseRestrictionOperator operator, Date value)
			throws VFrameException {
		return new VDatabaseRestriction(VDatabaseField.field(fieldName),
				operator, VDatabaseValue.date(value));
	}

	protected static VDatabaseRestriction newWithFieldAndValue(String fieldName,
			VDatabaseRestrictionOperator operator, Object... value)
			throws VFrameException {
		if (value == null) {
			throw new VDatabaseRestrictionValueIsNullException();
		}
		int valueCount = value.length;
		VDatabaseValue values[] = new VDatabaseValue[valueCount];
		for (int i = 0; i < valueCount; i++) {
			Object currentValue = value[i];
			Class<?> valueClass = currentValue.getClass();
			if (currentValue instanceof VDatabaseValue) {
				values[i] = (VDatabaseValue) currentValue;
			} else if (valueClass == short.class || valueClass == int.class
					|| valueClass == long.class || valueClass == double.class
					|| valueClass == Integer.class
					|| valueClass == Number.class) {
				values[i] = VDatabaseValue.number((Number) currentValue);
			} else if (valueClass == String.class) {
				values[i] = VDatabaseValue.string((String) currentValue);
			} else if (valueClass == Date.class) {
				values[i] = VDatabaseValue.date((Date) currentValue);
			} else if (valueClass == VDatabaseField.class) {
				values[i] = VDatabaseValue.field((VDatabaseField) currentValue);
			} else {
				throw new VDatabaseRestrictionValueTypeNotSupportedException(
						currentValue.getClass().getName());
			}
		}
		return new VDatabaseRestriction(VDatabaseField.field(fieldName),
				operator, values);
	}

	protected static VDatabaseRestriction newWithFieldAndValue(
			VDatabaseField fieldName, VDatabaseRestrictionOperator operator,
			VDatabaseValue... values) throws VFrameException {
		return new VDatabaseRestriction(fieldName, operator, values);
	}

	protected static VDatabaseRestriction newWithRestrictions(
			VDatabaseRestrictionLogicOperator logicOperator,
			VDatabaseRestriction... restrictions) throws VFrameException {
		return new VDatabaseRestriction(logicOperator, restrictions);
	}

	public static VDatabaseRestriction lessThan(VDatabaseField fieldName,
			Number value) throws VFrameException {
		return VDatabaseRestriction.newWithFieldAndValue(fieldName,
				VDatabaseRestrictionOperator.LESS_THAN,
				VDatabaseValue.number(value));
	}

	public static VDatabaseRestriction lessThanOrEqualTo(VDatabaseField fieldName,
			Number value) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.LESS_THAN_OR_EQUAL_TO,
						VDatabaseValue.number(value));
	}

	public static VDatabaseRestriction equalTo(VDatabaseField fieldName,
			Number value) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.EQUAL_TO,
						VDatabaseValue.number(value));
	}

	public static VDatabaseRestriction greaterThanOrEqualTo(
			VDatabaseField fieldName, Number value) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.GREATER_THAN_OR_EQUAL_TO,
						VDatabaseValue.number(value));
	}

	public static VDatabaseRestriction greaterThan(VDatabaseField fieldName,
			Number value) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.GREATER_THAN,
						VDatabaseValue.number(value));
	}

	public static VDatabaseRestriction between(VDatabaseField fieldName,
			Number valueLow, Number valueHigh) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.BETWEEN,
						VDatabaseValue.number(valueLow),
						VDatabaseValue.number(valueHigh));
	}

	public static VDatabaseRestriction beginWith(VDatabaseField fieldName,
			String value) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.BEGIN_WITH,
						VDatabaseValue.string(value));
	}

	public static VDatabaseRestriction endWith(VDatabaseField fieldName,
			String value) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.END_WITH,
						VDatabaseValue.string(value));
	}

	public static VDatabaseRestriction is(VDatabaseField fieldName, String value)
			throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.IS,
						VDatabaseValue.string(value));
	}

	public static VDatabaseRestriction have(VDatabaseField fieldName, String value)
			throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.HAVE,
						VDatabaseValue.string(value));
	}

	public static VDatabaseRestriction beginWithIgnoreCases(
			VDatabaseField fieldName, String value) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.BEGIN_WITH_IGNORE_CASES,
						VDatabaseValue.string(value));
	}

	public static VDatabaseRestriction endWithIgnoreCases(VDatabaseField fieldName,
			String value) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.END_WITH_IGNORE_CASES,
						VDatabaseValue.string(value));
	}

	public static VDatabaseRestriction isIgnoreCases(VDatabaseField fieldName,
			String value) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.IS_IGNORE_CASES,
						VDatabaseValue.string(value));
	}

	public static VDatabaseRestriction haveIgnoreCases(VDatabaseField fieldName,
			String value) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.HAVE_IGNORE_CASES,
						VDatabaseValue.string(value));
	}

	public static VDatabaseRestriction oracleTextContains(VDatabaseField fieldName,
			String value, Number scoreIndex) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.ORACLE_TEXT_CONTAINS,
						VDatabaseValue.string(value),
						VDatabaseValue.number(scoreIndex));
	}

	public static VDatabaseRestriction oracleTextContains(VDatabaseField fieldName,
			VDatabaseValue value, Number scoreIndex) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.ORACLE_TEXT_CONTAINS,
						value, VDatabaseValue.number(scoreIndex));
	}

	public static VDatabaseRestriction lessThan(String fieldName, Number value)
			throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.LESS_THAN,
						VDatabaseValue.number(value));
	}

	public static VDatabaseRestriction lessThanOrEqualTo(String fieldName,
			Number value) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.LESS_THAN_OR_EQUAL_TO,
						VDatabaseValue.number(value));
	}

	public static VDatabaseRestriction equalTo(String fieldName, Number value)
			throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.EQUAL_TO,
						VDatabaseValue.number(value));
	}

	public static VDatabaseRestriction greaterThanOrEqualTo(String fieldName,
			Number value) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.GREATER_THAN_OR_EQUAL_TO,
						VDatabaseValue.number(value));
	}

	public static VDatabaseRestriction greaterThan(String fieldName, Number value)
			throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.GREATER_THAN,
						VDatabaseValue.number(value));
	}

	public static VDatabaseRestriction between(String fieldName, Number valueLow,
			Number valueHigh) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.BETWEEN,
						VDatabaseValue.number(valueLow),
						VDatabaseValue.number(valueHigh));
	}

	public static VDatabaseRestriction beginWith(String fieldName, String value)
			throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.BEGIN_WITH,
						VDatabaseValue.string(value));
	}

	public static VDatabaseRestriction endWith(String fieldName, String value)
			throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.END_WITH,
						VDatabaseValue.string(value));
	}

	public static VDatabaseRestriction is(String fieldName, String value)
			throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.IS,
						VDatabaseValue.string(value));
	}

	public static VDatabaseRestriction have(String fieldName, String value)
			throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.HAVE,
						VDatabaseValue.string(value));
	}

	public static VDatabaseRestriction beginWithIgnoreCases(String fieldName,
			String value) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.BEGIN_WITH_IGNORE_CASES,
						VDatabaseValue.string(value));
	}

	public static VDatabaseRestriction endWithIgnoreCases(String fieldName,
			String value) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.END_WITH_IGNORE_CASES,
						VDatabaseValue.string(value));
	}

	public static VDatabaseRestriction isIgnoreCases(String fieldName, String value)
			throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.IS_IGNORE_CASES,
						VDatabaseValue.string(value));
	}

	public static VDatabaseRestriction haveIgnoreCases(String fieldName,
			String value) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.HAVE_IGNORE_CASES,
						VDatabaseValue.string(value));
	}

	public static VDatabaseRestriction oracleTextContains(String fieldName,
			String value, Number scoreIndex) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.ORACLE_TEXT_CONTAINS,
						VDatabaseValue.string(value),
						VDatabaseValue.number(scoreIndex));
	}

	public static VDatabaseRestriction oracleTextContains(String fieldName,
			VDatabaseValue value, Number scoreIndex) throws VFrameException {
		return VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.ORACLE_TEXT_CONTAINS,
						value, VDatabaseValue.number(scoreIndex));
	}

	private VDatabaseRestriction(VDatabaseField fieldName,
			VDatabaseRestrictionOperator operator, VDatabaseValue... values)
			throws VFrameException {
		if (fieldName == null) {
			throw new VFieldNameIsNullException();
		}
		if (operator == null) {
			throw new VOperatorIsNullException();
		}
		if (values == null) {
			throw new VDatabaseRestrictionValuesIsNullException();
		}
		this.fieldName = fieldName;
		this.restrictionElement = false;
		this.operator = operator;
		this.logicOperator = null;
		this.values = values;
		this.restrictions = null;
	}

	private VDatabaseRestriction(
			VDatabaseRestrictionLogicOperator logicOperator,
			VDatabaseRestriction... restrictions) throws VFrameException {
		if (logicOperator == null) {
			throw new VLogicOperatorIsNullException();
		}
		if (restrictions == null) {
			throw new VDatabaseRestrictionValuesIsNullException();
		}
		this.fieldName = null;
		this.restrictionElement = true;
		this.operator = null;
		this.logicOperator = logicOperator;
		this.values = null;
		this.restrictions = restrictions;
	}
	
	public VDatabaseRestriction and(VDatabaseRestriction... restrictions) throws VFrameException {
		VDatabaseRestriction newRestrictions[] = new VDatabaseRestriction[restrictions.length + 1];
		for (int i = 0; i < restrictions.length; i++) {
			newRestrictions[i+1] = restrictions[i];
		}
		newRestrictions[0] = this;
		restrictions = null;
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, newRestrictions);
	}
	
	public VDatabaseRestriction or(VDatabaseRestriction... restrictions) throws VFrameException {
		VDatabaseRestriction newRestrictions[] = new VDatabaseRestriction[restrictions.length + 1];
		for (int i = 0; i < restrictions.length; i++) {
			newRestrictions[i+1] = restrictions[i];
		}
		newRestrictions[0] = this;
		restrictions = null;
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, newRestrictions);
	}

	public VDatabaseRestriction andLessThan(VDatabaseField fieldName,
			Number value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.LESS_THAN,
						VDatabaseValue.number(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andLessThanOrEqualTo(VDatabaseField fieldName,
			Number value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.LESS_THAN_OR_EQUAL_TO,
						VDatabaseValue.number(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andEqualTo(VDatabaseField fieldName,
			Number value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.EQUAL_TO,
						VDatabaseValue.number(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andGreaterThanOrEqualTo(
			VDatabaseField fieldName, Number value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.GREATER_THAN_OR_EQUAL_TO,
						VDatabaseValue.number(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andGreaterThan(VDatabaseField fieldName,
			Number value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.GREATER_THAN,
						VDatabaseValue.number(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andBetween(VDatabaseField fieldName,
			Number valueLow, Number valueHigh) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.BETWEEN,
						VDatabaseValue.number(valueLow),
						VDatabaseValue.number(valueHigh));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andBeginWith(VDatabaseField fieldName,
			String value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.BEGIN_WITH,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andEndWith(VDatabaseField fieldName,
			String value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.END_WITH,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andIs(VDatabaseField fieldName, String value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.IS,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andHave(VDatabaseField fieldName, String value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.HAVE,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andBeginWithIgnoreCases(
			VDatabaseField fieldName, String value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.BEGIN_WITH_IGNORE_CASES,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andEndWithIgnoreCases(VDatabaseField fieldName,
			String value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.END_WITH_IGNORE_CASES,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andIsIgnoreCases(VDatabaseField fieldName,
			String value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.IS_IGNORE_CASES,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andHaveIgnoreCases(VDatabaseField fieldName,
			String value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.HAVE_IGNORE_CASES,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andOracleTextContains(VDatabaseField fieldName,
			String value, Number scoreIndex) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.ORACLE_TEXT_CONTAINS,
						VDatabaseValue.string(value),
						VDatabaseValue.number(scoreIndex));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andOracleTextContains(VDatabaseField fieldName,
			VDatabaseValue value, Number scoreIndex) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.ORACLE_TEXT_CONTAINS,
						value, VDatabaseValue.number(scoreIndex));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andLessThan(String fieldName, Number value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.LESS_THAN,
						VDatabaseValue.number(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andLessThanOrEqualTo(String fieldName,
			Number value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.LESS_THAN_OR_EQUAL_TO,
						VDatabaseValue.number(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andEqualTo(String fieldName, Number value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.EQUAL_TO,
						VDatabaseValue.number(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andGreaterThanOrEqualTo(String fieldName,
			Number value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.GREATER_THAN_OR_EQUAL_TO,
						VDatabaseValue.number(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andGreaterThan(String fieldName, Number value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.GREATER_THAN,
						VDatabaseValue.number(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andBetween(String fieldName, Number valueLow,
			Number valueHigh) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.BETWEEN,
						VDatabaseValue.number(valueLow),
						VDatabaseValue.number(valueHigh));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andBeginWith(String fieldName, String value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.BEGIN_WITH,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andEndWith(String fieldName, String value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.END_WITH,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andIs(String fieldName, String value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.IS,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andHave(String fieldName, String value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.HAVE,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andBeginWithIgnoreCases(String fieldName,
			String value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.BEGIN_WITH_IGNORE_CASES,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andEndWithIgnoreCases(String fieldName,
			String value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.END_WITH_IGNORE_CASES,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andIsIgnoreCases(String fieldName, String value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.IS_IGNORE_CASES,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andHaveIgnoreCases(String fieldName,
			String value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.HAVE_IGNORE_CASES,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andOracleTextContains(String fieldName,
			String value, Number scoreIndex) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.ORACLE_TEXT_CONTAINS,
						VDatabaseValue.string(value),
						VDatabaseValue.number(scoreIndex));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction andOracleTextContains(String fieldName,
			VDatabaseValue value, Number scoreIndex) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.ORACLE_TEXT_CONTAINS,
						value, VDatabaseValue.number(scoreIndex));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.AND, this, another);
	}

	public VDatabaseRestriction orLessThan(VDatabaseField fieldName,
			Number value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.LESS_THAN,
						VDatabaseValue.number(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orLessThanOrEqualTo(VDatabaseField fieldName,
			Number value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.LESS_THAN_OR_EQUAL_TO,
						VDatabaseValue.number(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orEqualTo(VDatabaseField fieldName, Number value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.EQUAL_TO,
						VDatabaseValue.number(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orGreaterThanOrEqualTo(
			VDatabaseField fieldName, Number value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.GREATER_THAN_OR_EQUAL_TO,
						VDatabaseValue.number(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orGreaterThan(VDatabaseField fieldName,
			Number value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.GREATER_THAN,
						VDatabaseValue.number(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orBetween(VDatabaseField fieldName,
			Number valueLow, Number valueHigh) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.BETWEEN,
						VDatabaseValue.number(valueLow),
						VDatabaseValue.number(valueHigh));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orBeginWith(VDatabaseField fieldName,
			String value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.BEGIN_WITH,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orEndWith(VDatabaseField fieldName, String value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.END_WITH,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orIs(VDatabaseField fieldName, String value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.IS,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orHave(VDatabaseField fieldName, String value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.HAVE,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orBeginWithIgnoreCases(
			VDatabaseField fieldName, String value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.BEGIN_WITH_IGNORE_CASES,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orEndWithIgnoreCases(VDatabaseField fieldName,
			String value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.END_WITH_IGNORE_CASES,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orIsIgnoreCases(VDatabaseField fieldName,
			String value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.IS_IGNORE_CASES,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orHaveIgnoreCases(VDatabaseField fieldName,
			String value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.HAVE_IGNORE_CASES,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orOracleTextContains(VDatabaseField fieldName,
			String value, Number scoreIndex) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.ORACLE_TEXT_CONTAINS,
						VDatabaseValue.string(value),
						VDatabaseValue.number(scoreIndex));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orOracleTextContains(VDatabaseField fieldName,
			VDatabaseValue value, Number scoreIndex) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(fieldName,
						VDatabaseRestrictionOperator.ORACLE_TEXT_CONTAINS,
						value, VDatabaseValue.number(scoreIndex));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orLessThan(String fieldName, Number value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.LESS_THAN,
						VDatabaseValue.number(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orLessThanOrEqualTo(String fieldName,
			Number value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.LESS_THAN_OR_EQUAL_TO,
						VDatabaseValue.number(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orEqualTo(String fieldName, Number value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.EQUAL_TO,
						VDatabaseValue.number(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orGreaterThanOrEqualTo(String fieldName,
			Number value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.GREATER_THAN_OR_EQUAL_TO,
						VDatabaseValue.number(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orGreaterThan(String fieldName, Number value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.GREATER_THAN,
						VDatabaseValue.number(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orBetween(String fieldName, Number valueLow,
			Number valueHigh) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.BETWEEN,
						VDatabaseValue.number(valueLow),
						VDatabaseValue.number(valueHigh));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orBeginWith(String fieldName, String value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.BEGIN_WITH,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orEndWith(String fieldName, String value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.END_WITH,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orIs(String fieldName, String value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.IS,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orHave(String fieldName, String value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.HAVE,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orBeginWithIgnoreCases(String fieldName,
			String value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.BEGIN_WITH_IGNORE_CASES,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orEndWithIgnoreCases(String fieldName,
			String value) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.END_WITH_IGNORE_CASES,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orIsIgnoreCases(String fieldName, String value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.IS_IGNORE_CASES,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orHaveIgnoreCases(String fieldName, String value)
			throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.HAVE_IGNORE_CASES,
						VDatabaseValue.string(value));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orOracleTextContains(String fieldName,
			String value, Number scoreIndex) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.ORACLE_TEXT_CONTAINS,
						VDatabaseValue.string(value),
						VDatabaseValue.number(scoreIndex));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	public VDatabaseRestriction orOracleTextContains(String fieldName,
			VDatabaseValue value, Number scoreIndex) throws VFrameException {
		VDatabaseRestriction another = VDatabaseRestriction
				.newWithFieldAndValue(VDatabaseField.field(fieldName),
						VDatabaseRestrictionOperator.ORACLE_TEXT_CONTAINS,
						value, VDatabaseValue.number(scoreIndex));
		return VDatabaseRestriction.newWithRestrictions(
				VDatabaseRestrictionLogicOperator.OR, this, another);
	}

	protected boolean isEqualTo(VDatabaseRestriction another,
			boolean caseSensitive) {
		if (another == null) {
			return false;
		}
		if (this.restrictionElement != another.restrictionElement) {
			return false;
		}
		if (this.restrictionElement) {
			if (this.logicOperator != another.logicOperator) {
				return false;
			}
			if (this.restrictions.length != another.restrictions.length) {
				return false;
			}
			for (int i = 0; i < this.restrictions.length; i++) {
				if (!(this.restrictions[i].isEqualTo(another.restrictions[i],
						caseSensitive))) {
					return false;
				}
			}
		} else {
			if (this.operator != another.operator) {
				return false;
			}
			if (this.values.length != another.values.length) {
				return false;
			}
			if (!(this.fieldName.isEqualTo(another.fieldName))) {
				return false;
			}
			if (this.operator == VDatabaseRestrictionOperator.BEGIN_WITH_IGNORE_CASES || this.operator == VDatabaseRestrictionOperator.END_WITH_IGNORE_CASES || this.operator == VDatabaseRestrictionOperator.HAVE_IGNORE_CASES || this.operator == VDatabaseRestrictionOperator.IS_IGNORE_CASES) {
				caseSensitive = false;
			} else {
				caseSensitive = true;
			}
			for (int i = 0; i < this.values.length; i++) {
				if (!(this.values[i]
						.isEqualTo(another.values[i], caseSensitive))) {
					return false;
				}
			}
		}
		return true;
	}

	@Override
	public String toString(boolean rawValueData, Map<String, String> nameMap)
			throws VFrameException {
		if (this.restrictionElement) {
			return this.logicOperator.toString(rawValueData, null, nameMap,
					restrictions);
		} else {
			return this.operator.toString(rawValueData,
					fieldName.toString(false, nameMap), nameMap, values);
		}
	}
}
